﻿using Newtonsoft.Json.Linq;
using ServerCrafter.ClassLibrary.Tools;
using System;
using System.IO;
using System.Linq;

namespace ServerCrafter.ClassLibrary
{
    public static class PluginManager
    {
        public sealed class InstalledPlugins
        {
            public static string[] List;
            public static int Count;

            public static void CreateList()
            {
                Logger.WriteInfo("Installed plugins list requested. Getting list.");
                Logger.WriteInfo("Looking in directory " + Settings.ServerStartInfo.WorkingDirectory + @"plugins\" +
                                 " for plugins.");
                try
                {
                    List = Directory.GetFiles(Settings.ServerStartInfo.WorkingDirectory + @"plugins\",
                                              "*.jar",
                                              SearchOption.TopDirectoryOnly);
                    Logger.WriteInfo("Successfully acquired plugin list.");
                }
                catch (ArgumentNullException exception)
                {
                    Logger.WriteWarning("Could not get plugin list! Path is null.");
                    Logger.WriteWarning("\tException: " + exception);
                }
                catch (ArgumentException exception)
                {
                    Logger.WriteWarning(
                        "Could not get plugin list! path is a zero-length string, contains only white space, or contains one or more invalid characters as defined by InvalidPathChars.");
                    Logger.WriteWarning("\tException: " + exception);
                }
                catch (PathTooLongException exception)
                {
                    Logger.WriteWarning(
                        "Could not get plugin list! The specified path, file name, or both exceed the system-defined maximum length.");
                    Logger.WriteWarning("\tException: " + exception);
                }
                catch (DirectoryNotFoundException exception)
                {
                    Logger.WriteWarning(
                        "Could not get plugin list! The specified path is invalid (for example, it is on an unmapped drive).");
                    Logger.WriteWarning("\tException: " + exception);
                }
                catch (IOException exception)
                {
                    Logger.WriteWarning("Could not get plugin list! Path is a file name.");
                    Logger.WriteWarning("\tException: " + exception);
                }

                Count = List.Count();
                for (var index = 0; index < Count; index++)
                {
                    List[index] = Path.GetFileNameWithoutExtension(List[index]);
                }
            }
        }

        public static class Plugins
        {
            public static string[,] List;
            internal static int Count;

            public static void CreateList()
            {
                // Checks when the plugin list was last downloaded.
                // If it was today, it doesn't download it again.
                var lastDownloadPluginList = Properties.Settings.Default.LastDownloadPluginsList;
                if (lastDownloadPluginList.Year == DateTime.Now.Year &&
                    lastDownloadPluginList.Month == DateTime.Now.Month &&
                    lastDownloadPluginList.Day == DateTime.Now.Day)
                {
                    BinarySerializer.Deserialize("plugins.list", out List);
                    Count = Properties.Settings.Default.PluginCount;
                    return;
                }

                Logger.WriteInfo("Plugin list requested. Downloading plugin list.");
                Parse(WebClient.DownloadString(BukGetApi.PLUGINLIST));

                BinarySerializer.Serialize("plugins.list", List);
                Properties.Settings.Default.PluginCount = Count;
                Properties.Settings.Default.LastDownloadPluginsList = DateTime.Now;
                Properties.Settings.Default.Save();
                Properties.Settings.Default.Upgrade();
            }

            private static void Parse(string rawList)
            {
                Logger.WriteInfo("Plugin list downloaded. Parsing plugin list.");
                var pluginsArray = JArray.Parse(rawList);
                Count = pluginsArray.Count;
                Logger.WriteInfo("Plugin count: " + Count + ".");

                List = new string[Count, 11];
                foreach (var index in pluginsArray.Select(pluginsArray.IndexOf))
                {
                    // Adds basic plugin information to the List array
                    List[index, BukGetApi.PLUGIN_NAME] = (string)pluginsArray[index]["plugin_name"];
                    List[index, BukGetApi.PLUGIN_SLUG] = (string)pluginsArray[index]["slug"];
                    List[index, BukGetApi.PLUGIN_DESCRIPTION] = (string)pluginsArray[index]["description"];
                    List[index, BukGetApi.PLUGIN_LOGO] = (string)pluginsArray[index]["logo_full"];

                    // Adds information about the plugin's newest version to the List array
                    var versionsArray = pluginsArray[index]["versions"];
                    List[index, BukGetApi.PLUGIN_VERSION_VERSION] = (string)versionsArray[0]["version"];
                    List[index, BukGetApi.PLUGIN_VERSION_TYPE] = (string)versionsArray[0]["type"];
                    List[index, BukGetApi.PLUGIN_VERSION_STATUS] = (string)versionsArray[0]["status"];
                    List[index, BukGetApi.PLUGIN_VERSION_RELEASEDATE] = (string)versionsArray[0]["date"];
                    List[index, BukGetApi.PLUGIN_VERSION_DOWNLOADLINK] = (string)versionsArray[0]["download"];
                    if (!(Convert.ToString(versionsArray[0]).Contains("\"game_versions\": []"))) { List[index, BukGetApi.PLUGIN_VERSION_GAMEVERSION] = (string)versionsArray[0]["game_versions"][0]; }

                    // Adds categories to the plugin List array
                    var categoriesArray = pluginsArray[index]["categories"];
                    var categoriesIndex = 0;
                    foreach (var category in categoriesArray)
                    {
                        if (List[index, BukGetApi.PLUGIN_CATEGORIES] != null)
                            List[index, BukGetApi.PLUGIN_CATEGORIES] += ", ";
                        List[index, BukGetApi.PLUGIN_CATEGORIES] = (string)categoriesArray[categoriesIndex];
                        categoriesIndex++;
                    }
                }
                Logger.WriteInfo("Parsing of plugin list has been completed.");
            }
        }

        private static class BukGetApi
        {
            public const string PLUGINLIST =
                "http://api.bukget.org/3//plugins?fields=slug,plugin_name,description,versions.version,versions.game_versions,versions.download,versions.type,versions.status,versions.date,logo_full,categories";

            public const int PLUGIN_NAME = 0;
            public const int PLUGIN_SLUG = 1;
            public const int PLUGIN_DESCRIPTION = 2;
            public const int PLUGIN_LOGO = 3;
            public const int PLUGIN_VERSION_VERSION = 4;
            public const int PLUGIN_VERSION_GAMEVERSION = 5;
            public const int PLUGIN_VERSION_TYPE = 6;
            public const int PLUGIN_VERSION_STATUS = 7;
            public const int PLUGIN_VERSION_RELEASEDATE = 8;
            public const int PLUGIN_VERSION_DOWNLOADLINK = 9;
            public const int PLUGIN_CATEGORIES = 10;
        }
    }
}